package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.enums.FlowType;
import com.warm.flow.core.dto.FlowParams;
import com.warm.flow.core.entity.Instance;
import com.warm.flow.core.enums.SkipType;
import com.warm.flow.core.service.InsService;
import com.warm.tools.utils.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.TestLeaveMapper;
import com.ruoyi.system.domain.TestLeave;
import com.ruoyi.system.service.ITestLeaveService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * OA 请假申请Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-03-07
 */
@Service
public class TestLeaveServiceImpl implements ITestLeaveService 
{
    @Autowired
    private TestLeaveMapper testLeaveMapper;

    @Resource
    private InsService insService;

    /**
     * 查询OA 请假申请
     * 
     * @param id OA 请假申请主键
     * @return OA 请假申请
     */
    @Override
    public TestLeave selectTestLeaveById(String id)
    {
        return testLeaveMapper.selectTestLeaveById(id);
    }

    /**
     * 查询OA 请假申请列表
     * 
     * @param testLeave OA 请假申请
     * @return OA 请假申请
     */
    @Override
    public List<TestLeave> selectTestLeaveList(TestLeave testLeave)
    {
        return testLeaveMapper.selectTestLeaveList(testLeave);
    }

    /**
     * 新增OA 请假申请
     * 
     * @param testLeave OA 请假申请
     * @return 结果
     */
    @Override
    public int insertTestLeave(TestLeave testLeave)
    {
        FlowType testLeaveSerial = getFlowType(testLeave);
        Long id = IdUtils.nextId();
        testLeave.setId(id.toString());
        LoginUser user = SecurityUtils.getLoginUser();
        FlowParams flowParams = FlowParams.build().flowCode(testLeaveSerial.getKey())
                .createBy(user.getUser().getUserId().toString())
                .nickName(user.getUser().getNickName());
        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        variable.put("testLeave", testLeave);
        flowParams.variable(variable);

        // 任务变量
        Map<String, Object> variableTask = new HashMap<>();
        variableTask.put("startFlow", true);
        flowParams.variableTask(variableTask);

        Instance instance = insService.start(String.valueOf(id), flowParams);
        testLeave.setId(id.toString());
        testLeave.setInstanceId(instance.getId());
        testLeave.setNodeCode(instance.getNodeCode());
        testLeave.setNodeName(instance.getNodeName());
        testLeave.setFlowStatus(instance.getFlowStatus());
        testLeave.setCreateTime(DateUtils.getNowDate());
        return testLeaveMapper.insertTestLeave(testLeave);
    }

    /**
     * 修改OA 请假申请
     * 
     * @param testLeave OA 请假申请
     * @return 结果
     */
    @Override
    public int updateTestLeave(TestLeave testLeave)
    {
        testLeave.setUpdateTime(DateUtils.getNowDate());
        return testLeaveMapper.updateTestLeave(testLeave);
    }

    /**
     * 批量删除OA 请假申请
     * 
     * @param ids 需要删除的OA 请假申请主键
     * @return 结果
     */
    @Override
    public int deleteTestLeaveByIds(String[] ids)
    {
        List<TestLeave> testLeaveList = testLeaveMapper.selectTestLeaveByIds(ids);
        if (testLeaveMapper.deleteTestLeaveByIds(ids) > 0) {
            List<Long> instanceIds = testLeaveList.stream().map(TestLeave::getInstanceId).collect(Collectors.toList());
            return insService.remove(instanceIds) ? 1: 0;
        }
        return 0;
    }

    /**
     * 删除OA 请假申请信息
     * 
     * @param id OA 请假申请主键
     * @return 结果
     */
    @Override
    public int deleteTestLeaveById(String id)
    {
        return testLeaveMapper.deleteTestLeaveById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int submit(String id) {
        TestLeave testLeave = testLeaveMapper.selectTestLeaveById(id);
        LoginUser user = SecurityUtils.getLoginUser();
        FlowParams flowParams = FlowParams.build().createBy(user.getUser().getUserId().toString())
                .nickName(user.getUser().getNickName())
                .skipType(SkipType.PASS.getKey());
        List<SysRole> roles = user.getUser().getRoles();
        if (Objects.nonNull(roles)) {
            List<String> roleList = roles.stream().map(role -> "role:" + role.getRoleId()).collect(Collectors.toList());
            flowParams.permissionFlag(roleList);
        }

        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        variable.put("testLeave", testLeave);
        flowParams.variable(variable);

        // 任务变量
        Map<String, Object> variableTask = new HashMap<>();
        variableTask.put("startFlow", false);
        flowParams.variableTask(variableTask);

        Instance instance = insService.skipByInsId(testLeave.getInstanceId(), flowParams);
        testLeave.setNodeCode(instance.getNodeCode());
        testLeave.setNodeName(instance.getNodeName());
        testLeave.setFlowStatus(instance.getFlowStatus());
        testLeave.setUpdateTime(DateUtils.getNowDate());
        return testLeaveMapper.updateTestLeave(testLeave);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int handle(TestLeave testLeave, Long taskId, String skipType, String message, String nodeCode) {
        // 设置流转参数
        LoginUser user = SecurityUtils.getLoginUser();
        FlowParams flowParams = FlowParams.build().createBy(user.getUser().getUserId().toString())
                .nickName(user.getUser().getNickName())
                .skipType(skipType)
                .nodeCode(nodeCode)
                .message(message);
        List<SysRole> roles = user.getUser().getRoles();
        if (Objects.nonNull(roles)) {
            List<String> roleList = roles.stream().map(role -> "role:" + role.getRoleId()).collect(Collectors.toList());
            flowParams.permissionFlag(roleList);
        }

        // 流程变量
        Map<String, Object> variable = new HashMap<>();
        variable.put("testLeave", testLeave);
        flowParams.variable(variable);

        // 任务变量
        Map<String, Object> variableTask = new HashMap<>();
        variableTask.put("startFlow", false);
        flowParams.variableTask(variableTask);

        // 互斥流程
        if (testLeave.getType() == 1 || testLeave.getType() == 4) {
            Map<String, String> skipCondition = new HashMap<>();
            // 如果是组长审批节点 需要判断请假时间确定跳转策略
            skipCondition.put("flag", String.valueOf(testLeave.getDay()));
            flowParams.skipCondition(skipCondition);
        }

        Instance instance = insService.skip(taskId, flowParams);
        testLeave.setNodeCode(instance.getNodeCode());
        testLeave.setNodeName(instance.getNodeName());
        testLeave.setFlowStatus(instance.getFlowStatus());
        return testLeaveMapper.updateTestLeave(testLeave);
    }

    private static FlowType getFlowType(TestLeave testLeave) {
        FlowType testLeaveSerial = FlowType.TEST_LEAVE_SERIAL1;
        if (testLeave.getType() == 1) {
            testLeaveSerial = FlowType.TEST_LEAVE_SERIAL2;
        } else if (testLeave.getType() == 2) {
            testLeaveSerial = FlowType.TEST_LEAVE_PARALLEL1;
        } else if (testLeave.getType() == 3) {
            testLeaveSerial = FlowType.TEST_LEAVE_PARALLEL2;
        } else if (testLeave.getType() == 4) {
            testLeaveSerial = FlowType.TEST_LEAVE_SERIAL3;
        }
        return testLeaveSerial;
    }
}
